#include "net_param.h"
#include "popen_interface.h"
#include "debug.h"
#include <stdlib.h>
#include <syslog.h>


enum
{
    NET_PORT_1 = 0,
    NET_PORT_2,

    NET_PORT_QTY,
};


typedef enum
{
    MODIFY_FLAG_NONE = 0,
    MODIFY_FLAG_IP   = (0x1 << 0),
    MODIFY_FLAG_MAC  = (0x1 << 1),
} netParamModify_t;


typedef struct
{
    netParamModify_t modFlag;
    uint16_t ip[4];
    uint16_t mac[6];
} netParam_t;


static netParam_t netParamModify[NET_PORT_QTY] = {0};


int NetParam_Init(void)
{
    uint8_t port, i;

    for(port = 0; port < NET_PORT_QTY; port++)
    {
        netParamModify[port].modFlag = MODIFY_FLAG_NONE;

        for(i = 0; i < 4; i++)
        {
            if(PopenInf_GetNetParam(POPENINF_NET_PARAM_TYPE_PORT1_IP0 + 10 * port + i, &netParamModify[port].ip[i]) != 0)
            {
                PRINT_WARN("Get failure");
                return -1;
            }
        }
        PRINT_DEBUG("%d.%d.%d.%d", netParamModify[port].ip[0], netParamModify[port].ip[1], netParamModify[port].ip[2], netParamModify[port].ip[3]);
        syslog(LOG_INFO, "%d.%d.%d.%d", netParamModify[port].ip[0], netParamModify[port].ip[1], netParamModify[port].ip[2], netParamModify[port].ip[3]);

        for(i = 0; i < 6; i++)
        {
            if(PopenInf_GetNetParam(POPENINF_NET_PARAM_TYPE_PORT1_MAC0 + 10 * port + i, &netParamModify[port].mac[i]) != 0)
            {
                PRINT_WARN("Get failure");
                return -1;
            }
        }
        PRINT_DEBUG("%02X:%02X:%02X:%02X:%02X:%02X", netParamModify[port].mac[0], netParamModify[port].mac[1], netParamModify[port].mac[2], netParamModify[port].mac[3], netParamModify[port].mac[4], netParamModify[port].mac[5]);
        syslog(LOG_INFO, "%02X:%02X:%02X:%02X:%02X:%02X", netParamModify[port].mac[0], netParamModify[port].mac[1], netParamModify[port].mac[2], netParamModify[port].mac[3], netParamModify[port].mac[4], netParamModify[port].mac[5]);
    }

    return 0;
}


int NetParam_Get(netParamType_t type, uint16_t *pValue)
{
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        NET_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }

    switch(type)
    {
        case NET_PARAM_TYPE_PORT1_IP0:
            *pValue = netParamModify[NET_PORT_1].ip[0];
            break;

        case NET_PARAM_TYPE_PORT1_IP1:
            *pValue = netParamModify[NET_PORT_1].ip[1];
            break;

        case NET_PARAM_TYPE_PORT1_IP2:
            *pValue = netParamModify[NET_PORT_1].ip[2];
            break;

        case NET_PARAM_TYPE_PORT1_IP3:
            *pValue = netParamModify[NET_PORT_1].ip[3];
            break;

        case NET_PARAM_TYPE_PORT1_MAC0:
            *pValue = netParamModify[NET_PORT_1].mac[0];
            break;

        case NET_PARAM_TYPE_PORT1_MAC1:
            *pValue = netParamModify[NET_PORT_1].mac[1];
            break;

        case NET_PARAM_TYPE_PORT1_MAC2:
            *pValue = netParamModify[NET_PORT_1].mac[2];
            break;

        case NET_PARAM_TYPE_PORT1_MAC3:
            *pValue = netParamModify[NET_PORT_1].mac[3];
            break;

        case NET_PARAM_TYPE_PORT1_MAC4:
            *pValue = netParamModify[NET_PORT_1].mac[4];
            break;

        case NET_PARAM_TYPE_PORT1_MAC5:
            *pValue = netParamModify[NET_PORT_1].mac[5];
            break;
        
        case NET_PARAM_TYPE_PORT2_IP0:
            *pValue = netParamModify[NET_PORT_2].ip[0];
            break;

        case NET_PARAM_TYPE_PORT2_IP1:
            *pValue = netParamModify[NET_PORT_2].ip[1];
            break;

        case NET_PARAM_TYPE_PORT2_IP2:
            *pValue = netParamModify[NET_PORT_2].ip[2];
            break;

        case NET_PARAM_TYPE_PORT2_IP3:
            *pValue = netParamModify[NET_PORT_2].ip[3];
            break;

        case NET_PARAM_TYPE_PORT2_MAC0:
            *pValue = netParamModify[NET_PORT_2].mac[0];
            break;

        case NET_PARAM_TYPE_PORT2_MAC1:
            *pValue = netParamModify[NET_PORT_2].mac[1];
            break;

        case NET_PARAM_TYPE_PORT2_MAC2:
            *pValue = netParamModify[NET_PORT_2].mac[2];
            break;

        case NET_PARAM_TYPE_PORT2_MAC3:
            *pValue = netParamModify[NET_PORT_2].mac[3];
            break;

        case NET_PARAM_TYPE_PORT2_MAC4:
            *pValue = netParamModify[NET_PORT_2].mac[4];
            break;

        case NET_PARAM_TYPE_PORT2_MAC5:
            *pValue = netParamModify[NET_PORT_2].mac[5];
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }
    
    return 0;
}


int NetParam_Set(netParamType_t type, uint16_t value)
{
    switch(type)
    {
    #define X_MACRO(a, b) case a:
        NET_PARAM_TYPE_TABLE
    #undef X_MACRO
            break;

        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }

    if(value > 255)
    {
        PRINT_WARN("Parameter error[%d]", type);
        return -1;
    }

    switch(type)
    {
        case NET_PARAM_TYPE_PORT1_IP0:
            if(value != netParamModify[NET_PORT_1].ip[0])
            {
                netParamModify[NET_PORT_1].ip[0] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT1_IP1:
            if(value != netParamModify[NET_PORT_1].ip[1])
            {
                netParamModify[NET_PORT_1].ip[1] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT1_IP2:
            if(value != netParamModify[NET_PORT_1].ip[2])
            {
                netParamModify[NET_PORT_1].ip[2] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT1_IP3:
            if(value != netParamModify[NET_PORT_1].ip[3])
            {
                netParamModify[NET_PORT_1].ip[3] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT1_MAC0:
            if(value != netParamModify[NET_PORT_1].mac[0])
            {
                netParamModify[NET_PORT_1].mac[0] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT1_MAC1:
            if(value != netParamModify[NET_PORT_1].mac[1])
            {
                netParamModify[NET_PORT_1].mac[1] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT1_MAC2:
            if(value != netParamModify[NET_PORT_1].mac[2])
            {
                netParamModify[NET_PORT_1].mac[2] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT1_MAC3:
            if(value != netParamModify[NET_PORT_1].mac[3])
            {
                netParamModify[NET_PORT_1].mac[3] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT1_MAC4:
            if(value != netParamModify[NET_PORT_1].mac[4])
            {
                netParamModify[NET_PORT_1].mac[4] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT1_MAC5:
            if(value != netParamModify[NET_PORT_1].mac[5])
            {
                netParamModify[NET_PORT_1].mac[5] = value;
                netParamModify[NET_PORT_1].modFlag |= MODIFY_FLAG_MAC;
            }
            break;
        
        case NET_PARAM_TYPE_PORT2_IP0:
            if(value != netParamModify[NET_PORT_2].ip[0])
            {
                netParamModify[NET_PORT_2].ip[0] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT2_IP1:
            if(value != netParamModify[NET_PORT_2].ip[1])
            {
                netParamModify[NET_PORT_2].ip[1] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT2_IP2:
            if(value != netParamModify[NET_PORT_2].ip[2])
            {
                netParamModify[NET_PORT_2].ip[2] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT2_IP3:
            if(value != netParamModify[NET_PORT_2].ip[3])
            {
                netParamModify[NET_PORT_2].ip[3] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_IP;
            }
            break;

        case NET_PARAM_TYPE_PORT2_MAC0:
            if(value != netParamModify[NET_PORT_2].mac[0])
            {
                netParamModify[NET_PORT_2].mac[0] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT2_MAC1:
            if(value != netParamModify[NET_PORT_2].mac[1])
            {
                netParamModify[NET_PORT_2].mac[1] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT2_MAC2:
            if(value != netParamModify[NET_PORT_2].mac[2])
            {
                netParamModify[NET_PORT_2].mac[2] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT2_MAC3:
            if(value != netParamModify[NET_PORT_2].mac[3])
            {
                netParamModify[NET_PORT_2].mac[3] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT2_MAC4:
            if(value != netParamModify[NET_PORT_2].mac[4])
            {
                netParamModify[NET_PORT_2].mac[4] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_MAC;
            }
            break;

        case NET_PARAM_TYPE_PORT2_MAC5:
            if(value != netParamModify[NET_PORT_2].mac[5])
            {
                netParamModify[NET_PORT_2].mac[5] = value;
                netParamModify[NET_PORT_2].modFlag |= MODIFY_FLAG_MAC;
            }
            break;
            
        default:
            PRINT_WARN("Parameter error[%d]", type);
            return -1;
    }
    
    return 0;
}


int NetParam_Update(void)
{
    int err = 0, i;
    uint16_t commitFlag = 0;

    if(netParamModify[NET_PORT_1].modFlag & MODIFY_FLAG_IP)
    {
        commitFlag++;
        if(PopenInf_SetIp(POPENINF_PORT_1, netParamModify[NET_PORT_1].ip) != 0)
        {
            err++;
            PRINT_WARN();
        }
    }
    if(netParamModify[NET_PORT_1].modFlag & MODIFY_FLAG_MAC)
    {
        commitFlag++;
        if(PopenInf_SetMac(POPENINF_PORT_1, netParamModify[NET_PORT_1].mac) != 0)
        {
            err++;
            PRINT_WARN();
        }
    }

    if(netParamModify[NET_PORT_2].modFlag & MODIFY_FLAG_IP)
    {
        commitFlag++;
        if(PopenInf_SetIp(POPENINF_PORT_2, netParamModify[NET_PORT_2].ip) != 0)
        {
            err++;
            PRINT_WARN();
        }
    }
    if(netParamModify[NET_PORT_2].modFlag & MODIFY_FLAG_MAC)
    {
        commitFlag++;
        if(PopenInf_SetMac(POPENINF_PORT_2, netParamModify[NET_PORT_2].mac) != 0)
        {
            err++;
            PRINT_WARN();
        }
    }

    if(commitFlag != 0)
    {
        if(system("uci commit network") != 0)
        {
            err++;
            PRINT_WARN();
        }
    }

    if(err != 0)
    {
        return -1;
    }

    for(i = 0; i < NET_PORT_QTY; i++)
    {
        netParamModify[i].modFlag = MODIFY_FLAG_NONE;
    }

    return 0;
}

